<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>服务器监控面板</title>
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            padding: 20px;
        }

        .container {
            max-width: 1400px;
            margin: 0 auto;
            background: rgba(255, 255, 255, 0.95);
            border-radius: 20px;
            box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
            overflow: hidden;
        }

        .header {
            background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
            color: white;
            padding: 30px;
            text-align: center;
        }

        .header h1 {
            font-size: 2.5rem;
            margin-bottom: 10px;
            font-weight: 300;
        }

        .header p {
            font-size: 1.1rem;
            opacity: 0.9;
        }

        .main-content {
            padding: 30px;
        }

        .controls-section {
            background: #f8f9fa;
            border-radius: 15px;
            padding: 25px;
            margin-bottom: 30px;
            border: 1px solid #e9ecef;
        }

        .control-group {
            display: flex;
            align-items: center;
            gap: 15px;
            margin-bottom: 20px;
            flex-wrap: wrap;
        }

        .control-group:last-child {
            margin-bottom: 0;
        }

        .control-group label {
            font-weight: 600;
            color: #495057;
            min-width: 80px;
        }

        .control-group select, .control-group button {
            padding: 10px 15px;
            border: 2px solid #dee2e6;
            border-radius: 8px;
            font-size: 14px;
            transition: all 0.3s ease;
        }

        .control-group select:focus, .control-group button:hover {
            border-color: #4facfe;
            outline: none;
            box-shadow: 0 0 0 3px rgba(79, 172, 254, 0.1);
        }

        .control-group button {
            background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
            color: white;
            border: none;
            cursor: pointer;
            font-weight: 600;
        }

        .control-group button:hover {
            transform: translateY(-2px);
            box-shadow: 0 5px 15px rgba(79, 172, 254, 0.3);
        }

        .info-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
            gap: 25px;
            margin-bottom: 30px;
        }

        .info-card {
            background: white;
            border-radius: 15px;
            padding: 25px;
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);
            border: 1px solid #e9ecef;
            transition: transform 0.3s ease, box-shadow 0.3s ease;
        }

        .info-card:hover {
            transform: translateY(-5px);
            box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
        }

        .info-card h3 {
            color: #495057;
            margin-bottom: 20px;
            font-size: 1.3rem;
            font-weight: 600;
            border-bottom: 2px solid #e9ecef;
            padding-bottom: 10px;
        }

        .info-item {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 8px 0;
            border-bottom: 1px solid #f8f9fa;
        }

        .info-item:last-child {
            border-bottom: none;
        }

        .info-label {
            font-weight: 500;
            color: #6c757d;
        }

        .info-value {
            font-weight: 600;
            color: #495057;
        }

        .charts-section {
            background: white;
            border-radius: 15px;
            padding: 30px;
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);
            border: 1px solid #e9ecef;
        }

        /* 新增：多图容器与卡片样式，避免页面无限拉长 */
        .charts-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
            gap: 20px;
        }

        .chart-card {
            background: #fff;
            border: 1px solid #e9ecef;
            border-radius: 12px;
            padding: 16px;
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05);
        }

        .chart-title {
            font-weight: 600;
            color: #495057;
            margin-bottom: 10px;
            font-size: 14px;
        }

        /* 固定每个图的高度，防止因响应式反复计算导致高度累计增长 */
        .chart-card canvas {
            width: 100% !important;
            height: 260px !important;
        }

        .charts-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 25px;
            flex-wrap: wrap;
            gap: 15px;
        }

        .charts-header h3 {
            color: #495057;
            font-size: 1.5rem;
            font-weight: 600;
        }

        .time-range-buttons {
            display: flex;
            gap: 10px;
            flex-wrap: wrap;
        }

        .time-btn {
            padding: 8px 16px;
            border: 2px solid #dee2e6;
            background: white;
            border-radius: 20px;
            cursor: pointer;
            transition: all 0.3s ease;
            font-size: 13px;
            font-weight: 500;
        }

        .time-btn:hover, .time-btn.active {
            background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
            color: white;
            border-color: #4facfe;
        }

        .chart-container {
            position: relative;
            height: 400px;
            margin-bottom: 20px;
            background: #fafafa;
            border-radius: 10px;
            padding: 15px;
        }

        .chart-container canvas {
            max-height: 100%;
            width: 100% !important;
            height: 100% !important;
        }

        .loading {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 200px;
            color: #6c757d;
            font-size: 1.1rem;
        }

        .error {
            color: #dc3545;
            text-align: center;
            padding: 20px;
            background: #f8d7da;
            border-radius: 10px;
            margin: 20px 0;
        }

        .no-data {
            text-align: center;
            color: #6c757d;
            padding: 40px;
            font-size: 1.1rem;
        }

        /* 响应式设计 */
        @media (max-width: 768px) {
            body {
                padding: 10px;
            }

            .header {
                padding: 20px;
            }

            .header h1 {
                font-size: 2rem;
            }

            .main-content {
                padding: 20px;
            }

            .control-group {
                flex-direction: column;
                align-items: flex-start;
            }

            .control-group label {
                min-width: auto;
            }

            .info-grid {
                grid-template-columns: 1fr;
            }

            .charts-header {
                flex-direction: column;
                align-items: flex-start;
            }

            .chart-card canvas {
                height: 220px !important;
            }
        }

        @media (max-width: 480px) {
            .header h1 {
                font-size: 1.5rem;
            }

            .time-range-buttons {
                justify-content: center;
            }

            .chart-card {
                padding: 12px;
            }
            .chart-card canvas {
                height: 200px !important;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>服务器监控面板</h1>
            <p>实时监控服务器性能指标</p>
        </div>

        <div class="main-content">
            <!-- 控制面板 -->
            <div class="controls-section">
                <div class="control-group">
                    <label for="ipSelect">选择服务器:</label>
                    <select id="ipSelect">
                        <option value="">请选择服务器IP</option>
                    </select>
                    <button onclick="loadLatestData()">刷新数据</button>
                </div>
            </div>

            <!-- 最新状态信息 -->
            <div class="info-grid">
                <div class="info-card">
                    <h3>系统信息</h3>
                    <div id="systemInfo">
                        <div class="loading">加载中...</div>
                    </div>
                </div>

                <div class="info-card">
                    <h3>CPU 使用率</h3>
                    <div id="cpuInfo">
                        <div class="loading">加载中...</div>
                    </div>
                </div>

                <div class="info-card">
                    <h3>内存使用情况</h3>
                    <div id="memoryInfo">
                        <div class="loading">加载中...</div>
                    </div>
                </div>

                <div class="info-card">
                    <h3>磁盘使用情况</h3>
                    <div id="diskInfo">
                        <div class="loading">加载中...</div>
                    </div>
                </div>
            </div>

            <!-- GPU 显存使用率图表（每GPU独立折线图） -->
            <div class="charts-section">
                <div class="charts-header">
                    <h3>GPU 显存使用率</h3>
                    <div class="time-range-select">
                        <label for="timeRangeSelect">时间范围:</label>
                        <select id="timeRangeSelect">
                            <option value="1">近一天</option>
                            <option value="3">近三天</option>
                            <option value="7" selected>近一周</option>
                            <option value="30">近一月</option>
                            <option value="90">近三月</option>
                        </select>
                    </div>
                </div>
                <div id="gpuChartsContainer" class="charts-grid"></div>
            </div>
        </div>
    </div>

    <script>
        // GPU图表相关函数
        let gpuCharts = [];
        let currentDays = 7; // 默认近一周

        function clearCharts() {
            // 销毁所有已有图表
            if (gpuCharts && gpuCharts.length) {
                gpuCharts.forEach(c => { try { c.destroy(); } catch (_) {} });
            }
            gpuCharts = [];
            const container = document.getElementById('gpuChartsContainer');
            if (container) container.innerHTML = '';
        }

        function renderGpuCharts(gpuData) {
            clearCharts();
            const container = document.getElementById('gpuChartsContainer');
            if (!gpuData || !gpuData.gpus || gpuData.gpus.length === 0) {
                const empty = document.createElement('div');
                empty.style.textAlign = 'center';
                empty.style.color = '#6c757d';
                empty.style.padding = '24px';
                empty.textContent = '暂无GPU数据';
                container.appendChild(empty);
                return;
            }

            const colors = ['#FF6384','#36A2EB','#FFCE56','#4BC0C0','#9966FF','#FF9F40','#C9CBCF','#7CB342'];

            gpuData.gpus.forEach((gpu, idx) => {
                const card = document.createElement('div');
                card.className = 'chart-card';
                const header = document.createElement('div');
                header.className = 'chart-title';
                header.textContent = `${gpu.name || 'GPU'} · 序号 ${gpu.index} · 显存 ${gpu.memory_mb ?? '未知'} MB`;
                const canvas = document.createElement('canvas');
                card.appendChild(header);
                card.appendChild(canvas);
                container.appendChild(card);

                const ctx = canvas.getContext('2d');
                const chart = new Chart(ctx, {
                    type: 'line',
                    data: {
                        datasets: [{
                            label: '显存使用率(%)',
                            data: gpu.points.map(p => ({ x: p.t, y: p.v })),
                            borderColor: colors[idx % colors.length],
                            backgroundColor: colors[idx % colors.length] + '20',
                            fill: false,
                            tension: 0.2,
                            pointRadius: 2,
                            pointHoverRadius: 5,
                            borderWidth: 2
                        }]
                    },
                    options: {
                        responsive: true,
                        maintainAspectRatio: false,
                        plugins: {
                            legend: { display: false }
                        },
                        scales: {
                            x: {
                                type: 'time',
                                time: {
                                    unit: currentDays <= 1 ? 'hour' : 'day',
                                    displayFormats: { hour: 'MM-dd HH:mm', day: 'MM-dd' }
                                },
                                title: { display: true, text: '时间' }
                            },
                            y: {
                                beginAtZero: true,
                                suggestedMin: 0,
                                suggestedMax: 100,
                                title: { display: true, text: '显存使用率 (%)' }
                            }
                        },
                        interaction: { intersect: false, mode: 'index' }
                    }
                });
                gpuCharts.push(chart);
            });
        }

        function changeTimeRange(days) {
            currentDays = days;
            refreshGpuCharts();
        }

        async function refreshGpuCharts() {
            const selectedIp = document.getElementById('ipSelect').value;
            
            if (!selectedIp) {
                return;
            }
            
            try {
                const response = await fetch(`/api/monitor/gpu_trend?ip=${selectedIp}&days=${currentDays}`);
                const result = await response.json();
                
                if (result.success && result.data) {
                    renderGpuCharts(result.data);
                } else {
                    console.error('获取GPU趋势数据失败:', result.message || '未知错误');
                    clearCharts();
                    const container = document.getElementById('gpuChartsContainer');
                    const msg = document.createElement('div');
                    msg.style.textAlign = 'center';
                    msg.style.color = '#6c757d';
                    msg.style.padding = '24px';
                    msg.textContent = '获取GPU数据失败';
                    container.appendChild(msg);
                }
            } catch (error) {
                console.error('获取GPU趋势数据失败:', error);
                clearCharts();
                const container = document.getElementById('gpuChartsContainer');
                const msg = document.createElement('div');
                msg.style.textAlign = 'center';
                msg.style.color = '#6c757d';
                msg.style.padding = '24px';
                msg.textContent = '网络请求失败';
                container.appendChild(msg);
            }
        }

        // 主要功能函数
        let refreshInterval;

        async function loadIPs() {
            try {
                const response = await fetch('/api/monitor/ips');
                const result = await response.json();
                
                const select = document.getElementById('ipSelect');
                select.innerHTML = '<option value="">请选择服务器IP</option>';
                
                if (result.success && result.data) {
                    result.data.forEach(ip => {
                        const option = document.createElement('option');
                        option.value = ip;
                        option.textContent = ip;
                        select.appendChild(option);
                    });
                } else {
                    console.error('加载IP列表失败:', result.message || '未知错误');
                }
            } catch (error) {
                console.error('加载IP列表失败:', error);
            }
        }

        async function loadLatestData(ip) {
            if (!ip) {
                const selectedIp = document.getElementById('ipSelect').value;
                if (!selectedIp) {
                    alert('请先选择服务器IP');
                    return;
                }
                ip = selectedIp;
            }
            
            try {
                const response = await fetch(`/api/monitor/latest?ip=${ip}`);
                const result = await response.json();
                
                if (result.success && result.data) {
                    updateInfoCards(result.data);
                } else {
                    showNoData(ip, result.message || '该IP暂无监控数据');
                }
            } catch (error) {
                console.error('获取最新数据失败:', error);
                showError('网络请求失败');
            }

            // 同时刷新GPU图表
            if (window.refreshGpuCharts) {
                window.refreshGpuCharts();
            }
        }

        function updateInfoCards(data) {
            // 系统信息
            const sys = document.getElementById('systemInfo');
            if (sys) {
                sys.innerHTML = `
                    <div class="info-item">
                        <span class="info-label">服务器IP:</span>
                        <span class="info-value">${data.ip || 'N/A'}</span>
                    </div>
                    <div class="info-item">
                        <span class="info-label">记录时间:</span>
                        <span class="info-value">${data.timestamp || 'N/A'}</span>
                    </div>
                `;
            }

            // CPU信息
            const cpu = document.getElementById('cpuInfo');
            if (cpu) {
                cpu.innerHTML = `
                    <div class="info-item">
                        <span class="info-label">CPU使用率:</span>
                        <span class="info-value">${data.cpuUsage ?? 'N/A'}%</span>
                    </div>
                `;
            }

            // 内存信息
            const mem = document.getElementById('memoryInfo');
            if (mem) {
                mem.innerHTML = `
                    <div class="info-item">
                        <span class="info-label">内存使用率:</span>
                        <span class="info-value">${data.memoryUsage ?? 'N/A'}%</span>
                    </div>
                `;
            }

            // 磁盘信息
            const disk = document.getElementById('diskInfo');
            if (disk) {
                disk.innerHTML = `
                    <div class="info-item">
                        <span class="info-label">磁盘使用率:</span>
                        <span class="info-value">${data.diskUsage ?? 'N/A'}%</span>
                    </div>
                `;
            }
        }

        function showError(message) {
            const sys = document.getElementById('systemInfo');
            if (sys) sys.innerHTML = `<div class="error">错误：${message}</div>`;
            ['cpuInfo', 'memoryInfo', 'diskInfo'].forEach(id => {
                const el = document.getElementById(id);
                if (el) el.innerHTML = '<div class="info-item"><span class="info-label">状态:</span><span class="info-value">—</span></div>';
            });
        }

        function showNoData(ip, message) {
            const sys = document.getElementById('systemInfo');
            if (sys) sys.innerHTML = `<div class="info-item"><span class="info-label">服务器IP:</span><span class="info-value">${ip}</span></div><div class="info-item"><span class="info-label">状态:</span><span class="info-value">${message}</span></div>`;
            ['cpuInfo', 'memoryInfo', 'diskInfo'].forEach(id => {
                const el = document.getElementById(id);
                if (el) el.innerHTML = '<div class="info-item"><span class="info-label">暂无数据</span><span class="info-value">—</span></div>';
            });
            if (window.refreshGpuCharts) {
                window.refreshGpuCharts();
            }
        }

        // 重复定义的changeTimeRange已在上方实现（带el参数），此处去除旧实现

        function startAutoRefresh() {
            if (refreshInterval) {
                clearInterval(refreshInterval);
            }
            refreshInterval = setInterval(() => {
                const selectedIp = document.getElementById('ipSelect').value;
                if (selectedIp) {
                    loadLatestData();
                }
            }, 30000); // 30秒刷新一次
        }

        // IP选择变化时的处理
        document.getElementById('ipSelect').addEventListener('change', function() {
            if (this.value) {
                loadLatestData();
                startAutoRefresh();
            } else {
                if (refreshInterval) {
                    clearInterval(refreshInterval);
                }
            }
        });

        // 页面加载完成后初始化
        document.addEventListener('DOMContentLoaded', function() {
            loadIPs();
            
            // 时间范围下拉绑定
            const timeSel = document.getElementById('timeRangeSelect');
            if (timeSel) {
                timeSel.addEventListener('change', function() {
                    changeTimeRange(parseInt(this.value, 10));
                });
            }

            // 将函数暴露到全局作用域
            window.refreshGpuCharts = refreshGpuCharts;
        });
    </script>
</body>
</html>